package com.spark.modules.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.spark.common.constants.Constants;
import com.spark.common.context.AuthenticationContextHolder;
import com.spark.common.core.Result;
import com.spark.common.core.entity.LoginUser;
import com.spark.common.core.entity.system.SysRole;
import com.spark.common.core.entity.system.SysUser;
import com.spark.common.exception.SparkException;
import com.spark.common.manager.AsyncManager;
import com.spark.common.manager.factory.AsyncLogFactory;
import com.spark.common.utils.JwtUtils;
import com.spark.common.utils.SecurityUtils;
import com.spark.modules.system.entity.params.LoginParams;
import com.spark.modules.system.entity.params.RegisterParams;
import com.spark.modules.system.entity.params.ResetPasswordParams;
import com.spark.modules.system.service.ISysPermissionService;
import com.spark.modules.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统登录服务
 *
 * @author LYCHEE
 * @date 2025/2/18 14:53
 */
@Service
public class SysLoginService {

    @Resource
    private JwtUtils jwtUtils;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ISysPermissionService sysPermissionService;
    @Resource
    private AuthenticationManager authenticationManager;

    /**
     * 登录接口
     *
     * @param params 登录参数
     * @return token
     */
    public String login(@Valid LoginParams params) {
        // 用户验证
        Authentication authentication = null;
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(params.getUsername()
                    , params.getPassword());
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me().execute(AsyncLogFactory.createLoginLog(params.getUsername(), Constants.LOGIN_FAIL, "账号或密码错误"));
                throw new SparkException("账号或密码错误");
            } else {
                AsyncManager.me().execute(AsyncLogFactory.createLoginLog(params.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
                throw new SparkException(e.getMessage());
            }
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncLogFactory.createLoginLog(params.getUsername(), Constants.LOGIN_SUCCESS, "登录成功"));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return jwtUtils.createToken(loginUser);
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    public Result<?> getUserInfo() {
        String username = SecurityUtils.getUsername();
        SysUser user = sysUserService.getUserByUsername(username);
        if (Objects.isNull(user)) {
            return Result.fail("用户信息获取失败");
        }
        // 对象转换为Map集合
        Map<String, Object> resultMap = BeanUtil.beanToMap(user);
        resultMap.remove("roleList");
        resultMap.remove("password");
        resultMap.put("roles", new ArrayList<String>());
        List<SysRole> roleList = user.getRoleList();
        if (!CollectionUtils.isEmpty(roleList)){
            Set<String> roles = roleList.stream().map(SysRole::getRoleCode).collect(Collectors.toSet());
            resultMap.put("roles", roles);
        }
        resultMap.put("realName",user.getNickname());
        return Result.ok(resultMap);
    }

    /**
     * 获取用户的权限编码
     *
     * @return 权限编码
     */
    public Result<?> getAccessCodes() {
        String userId = SecurityUtils.getUserId();
        List<String> perms = sysPermissionService.getAccessCodes(userId);
        return Result.ok(perms);
    }

    /**
     * 获取用户的菜单
     *
     * @return 菜单数据
     */
    public Result<?> getMenuList() {
        String userId = SecurityUtils.getUserId();
        // 获取用户菜单
        List<Map<String, Object>> menuNodes = sysPermissionService.selectMenuTreeByUserId(userId);
        return Result.ok(menuNodes);
    }

    /**
     * 刷新token
     *
     * @return 刷新
     */
    public Result<?> refresh(HttpServletRequest request) {
        LoginUser loginUser = jwtUtils.getLoginUser(request);
        jwtUtils.refreshToken(loginUser);
        return Result.ok("刷新成功");
    }

    /**
     * 退出登录
     *
     * @return 退出登录
     */
    public Result<?> logout(HttpServletRequest request) {
        LoginUser loginUser = jwtUtils.getLoginUser(request);
        jwtUtils.delLoginUser(loginUser.getToken());
        return Result.ok("退出登录成功!");
    }

    /**
     * 用户注册
     *
     * @param params 用户信息
     * @return 注册结果
     */
    public Result<?> register(@Valid RegisterParams params) {
        params.validTwicePassword();
        // 是否开启注册
        //String isRegister = ParamsUtils.getInputValByConfigField("isRegister");
        //if ("1".equals(isRegister)) {
        //    return Result.fail("暂不允许注册用户信息");
        //}
        //boolean existDataUsername = commonApi.checkExistData("sys_user", "username", params.getUsername(), null, null, null);
        //if (existDataUsername) {
        //    return Result.fail("账号已被使用!");
        //}
        //boolean existDataEmail = commonApi.checkExistData("sys_user", "email", params.getEmail(), null, null, null);
        //if (existDataEmail) {
        //    return Result.fail("邮箱已被使用!");
        //}
        if (!params.getPassword().equals(params.getConfirmPassword())){
            return Result.fail("两次密码不一致");
        }
        SysUser user = new SysUser();
        BeanUtils.copyProperties(params, user);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        boolean save = sysUserService.save(user);
        return Result.flag(save, "注册成功", "注册失败");
    }

    /**
     * 重置密码
     *
     * @param params 密码实体
     * @return 重置结果
     */
    public Result<?> resetPassword(@Valid ResetPasswordParams params) {
        SysUser user = sysUserService.getById(SecurityUtils.getUserId());
        if (Objects.isNull(user)){
            return Result.fail("无法重置密码");
        }
        if (!SecurityUtils.matchesPassword(params.getOriginalPassword(), user.getPassword())){
            return Result.fail("原密码不正确");
        }
        if (!params.getPassword().equals(params.getConfirmPassword())){
            return Result.fail("两次密码不一致");
        }
        user.setPassword(SecurityUtils.encryptPassword(params.getPassword()));
        boolean update = sysUserService.updateById(user);
        return Result.flag(update, "密码重置成功", "密码重置失败");
    }
}
